package com.yunxin.core.application.assembler;

import cn.hutool.core.collection.CollUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yunxin.common.utils.JacksonUtils;
import com.yunxin.core.application.dto.page.*;
import com.yunxin.core.domain.external.product.ProductExternalService;
import com.yunxin.core.domain.external.product.ProductFromPageElement;
import com.yunxin.core.infra.common.page.enums.PageComponentTypeEnum;
import com.yunxin.core.infra.common.page.enums.PushFrequencyTypeEnum;
import com.yunxin.core.infra.persistence.entity.page.PagePopupUserRecordDO;
import com.yunxin.core.infra.persistence.mapper.page.PagePopupUserRecordExtendMapper;
import com.yunxin.core.utils.infra.common.constant.CommonConstants;
import com.yunxin.core.utils.infra.utils.DateFormatUtils;
import com.yunxin.core.utils.infra.utils.DateUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zero°
 * @since 2023-07-17
 */
public enum PageDataAssembler {

    /**
     * 实例
     */
    X;

    /**
     * 处理PageInfoDataDTO数据
     * @param pageConfigInfoDTO pageConfigInfoDTO
     * @param productExternalService productExtendService
     */
    public void dealPageConfigInfoDTO(PageInfoDataDTO<PageComponentElementInfoDataDTO> pageConfigInfoDTO, ProductExternalService productExternalService) {
        if (Objects.nonNull(pageConfigInfoDTO)){
            pageConfigInfoDTO.getComponentData().forEach(x -> {
                if (PageComponentTypeEnum.PRODUCT_TITLE.getValue().equals(x.getComponentType())) {
                    x.getPageSubComponent().forEach(s -> {
                        Map<Long, ProductFromPageElement> map = getMap(s.getPageComponentElement(), productExternalService);
                        s.getPageComponentElement().forEach(e -> {
                            ProductFromPageElement pageElement = map.get(e.getProductId());
                            if (Objects.nonNull(pageElement)) {
                                PageElementProductTitleDTO pageElementProductTitleDTO = new PageElementProductTitleDTO();
                                pageElementProductTitleDTO.setHighestBorrowableAmount(pageElement.getHighestLoanAmount());
                                pageElementProductTitleDTO.setProductLabelingList(List.of(pageElement.getProductLabeling().split(",")));
                                pageElementProductTitleDTO.setProductSolGan(pageElement.getProductSolGan());
                                pageElementProductTitleDTO.setEquityDescription(JacksonUtils.X.parse(pageElement.getEquityDescription(), new TypeReference<>() {}));
                                e.setElementInfo(pageElementProductTitleDTO);
                            }
                        });
                    });
                }
                if (PageComponentTypeEnum.PRODUCT_LIST.getValue().equals(x.getComponentType())) {
                    x.getPageSubComponent().forEach(s -> {
                        Map<Long, ProductFromPageElement> map = getMap(s.getPageComponentElement(), productExternalService);
                        s.getPageComponentElement().forEach(e -> {
                            ProductFromPageElement pageElement = map.get(e.getProductId());
                            if (Objects.nonNull(pageElement)) {
                                PageElementProductListDTO pageElementProductListDTO = new PageElementProductListDTO();
                                pageElementProductListDTO.setHighestBorrowableAmount(pageElement.getHighestBorrowableAmount());
                                pageElementProductListDTO.setProductLabelingList(List.of(pageElement.getProductLabeling().split(",")));
                                pageElementProductListDTO.setSellingPoint(pageElement.getProductSolGan());
                                pageElementProductListDTO.setReferenceRate(JacksonUtils.X.parse(pageElement.getReferenceRate(), PageElementProductListDTO.ReferenceRate.class));
                                e.setElementInfo(pageElementProductListDTO);
                            }
                        });
                    });
                }
            });
        }
    }

    /**
     * 获取产品数据map
     * @param pageComponentElement pageComponentElement
     * @param productExternalService productExternalService
     * @return Map<Long, ProductFromPageElement>
     */
    private Map<Long, ProductFromPageElement> getMap(List<PageComponentElementInfoDataDTO> pageComponentElement, ProductExternalService productExternalService){
        Set<Long> productIds = pageComponentElement.stream().filter(p -> Objects.nonNull(p.getProductId())).map(PageComponentElementInfoDataDTO::getProductId).collect(Collectors.toSet());
        if (CollUtil.isEmpty(productIds)) {
            return Collections.emptyMap();
        }
        List<ProductFromPageElement> elements = productExternalService.listProductFromPageElementByIds(productIds);
        return elements.stream().collect(Collectors.toMap(ProductFromPageElement::getProductId, Function.identity()));
    }

    /**
     * 处理C端网关页面数据
     * @param pageConfig pageConfig
     * @param userCode userCode
     */
    public void dealGatewayPageConfigInfoDTO(PageInfoDataDTO<PageComponentElementInfoDataDTO> pageConfig, String userCode, PagePopupUserRecordExtendMapper pagePopupUserRecordExtendMapper,
                                             ProductExternalService productExternalService) {
        if (Objects.nonNull(pageConfig)) {
            Set<Long> productIds = CollUtil.newHashSet();
            pageConfig.getComponentData().forEach(x->{
                x.getPageSubComponent().forEach(y->{
                    productIds.addAll(y.getPageComponentElement().stream().map(PageComponentElementInfoDataDTO::getProductId).filter(Objects::nonNull).collect(Collectors.toSet()));
                });
            });
            //查询对接方式H5，满足投放时间，投放日期的产品
            List<ProductFromPageElement> productFromPageElements = productExternalService.listValidProductFromPageElementByIds(productIds);
            Map<Long, ProductFromPageElement> elementMap = productFromPageElements.stream().collect(Collectors.toMap(ProductFromPageElement::getProductId, Function.identity()));
            pageConfig.getComponentData().forEach(x -> {
                //移除对接方式H5，满足投放时间，投放日期的产品
                x.getPageSubComponent().forEach(s -> s.getPageComponentElement().removeIf(y-> !elementMap.containsKey(y.getProductId())));
                if (PageComponentTypeEnum.PRODUCT_TITLE.getValue().equals(x.getComponentType())) {
                    x.getPageSubComponent().forEach(s -> {
                        s.getPageComponentElement().forEach(e -> {
                            ProductFromPageElement pageElement = elementMap.get(e.getProductId());
                            if (Objects.nonNull(pageElement)) {
                                PageElementProductTitleDTO pageElementProductTitleDTO = new PageElementProductTitleDTO();
                                pageElementProductTitleDTO.setHighestBorrowableAmount(pageElement.getHighestLoanAmount());
                                pageElementProductTitleDTO.setProductLabelingList(List.of(pageElement.getProductLabeling().split(",")));
                                pageElementProductTitleDTO.setProductSolGan(pageElement.getProductSolGan());
                                pageElementProductTitleDTO.setEquityDescription(JacksonUtils.X.parse(pageElement.getEquityDescription(), new TypeReference<>() {}));
                                e.setElementInfo(pageElementProductTitleDTO);
                            }
                        });
                    });
                }
                if (PageComponentTypeEnum.PRODUCT_LIST.getValue().equals(x.getComponentType())) {
                    x.getPageSubComponent().forEach(s -> {
                        s.getPageComponentElement().forEach(e -> {
                            ProductFromPageElement pageElement = elementMap.get(e.getProductId());
                            if (Objects.nonNull(pageElement)) {
                                PageElementProductListDTO pageElementProductListDTO = new PageElementProductListDTO();
                                pageElementProductListDTO.setHighestBorrowableAmount(pageElement.getHighestBorrowableAmount());
                                pageElementProductListDTO.setProductLabelingList(List.of(pageElement.getProductLabeling().split(",")));
                                pageElementProductListDTO.setSellingPoint(pageElement.getProductSolGan());
                                pageElementProductListDTO.setReferenceRate(JacksonUtils.X.parse(pageElement.getReferenceRate(), PageElementProductListDTO.ReferenceRate.class));
                                e.setElementInfo(pageElementProductListDTO);
                            }
                        });
                    });
                }
                if (PageComponentTypeEnum.POPUP_WINDOW.getValue().equals(x.getComponentType())) {
                    x.getPageSubComponent().forEach(y -> y.getPageComponentElement().removeIf(z -> {
                                Integer pushFrequencyType = z.getPushFrequencyType();
                                if (PushFrequencyTypeEnum.ONCE.getType().equals(pushFrequencyType)) {
                                    PagePopupUserRecordDO pagePopupUserRecordDo = pagePopupUserRecordExtendMapper.selectByUserCodeAndElementCode(userCode, z.getElementCode());
                                    return Objects.nonNull(pagePopupUserRecordDo);
                                } else if (PushFrequencyTypeEnum.CUSTOM_TIME.getType().equals(pushFrequencyType)) {
                                    List<String> timeRuleList = z.getTimeRuleList();
                                    if (timeRuleList.size() == CommonConstants.TWO) {
                                        String startTime = timeRuleList.get(CommonConstants.ZERO);
                                        String endTime = timeRuleList.get(CommonConstants.ONE);
                                        if (StringUtils.isBlank(startTime) || StringUtils.isBlank(endTime)) {
                                            return false;
                                        }
                                        Date beginTime = DateFormatUtils.X.getDateFromFullStr(startTime, DateFormatUtils.DATE_SECOND_FORMAT);
                                        Date finishTime = DateFormatUtils.X.getDateFromFullStr(endTime, DateFormatUtils.DATE_SECOND_FORMAT);
                                        if (Objects.isNull(beginTime) || Objects.isNull(finishTime)) {
                                            return false;
                                        }
                                        return !DateUtils.X.belongCalendar(new Date(), beginTime, finishTime);
                                    }
                                }
                                return false;
                            })
                    );
                }
            });
        }
    }
}
